# 34~39 in only
# 12
# 1 3 5 6~11 14 15 do not output
# 12 low at start
import machine
import time
import ubinascii
import machine
from umqtt.robust import MQTTClient
from machine import Pin, PWM, Timer, RTC, I2C
import ntptime
import network
from ssd1306 import SSD1306_I2C
from ads1x15 import ADS1115

wlan_ssid = 'wifi名'
wlan_passwd = 'WiFi密码'

SERVER = "183.230.40.39"
SERVER_PORT = 6002
CLIENT_ID = "设备号"  # deviceID
TOPIC = b"$dp"
username = '产品号'  # productID
password = '设备详情页的设备描述'  # info

TOPIC1 = b"/设备号" #把设备号填入
tem = 0
sw1 = 0


data_stream_name_rw = ["o0", "o1", "o2", "o3", "o4", "o5", "o6", "o7", "o8", "L"]
data_stream_value_rw = [0, 0, 0, 0, 0, 0, 0, 0, 1, -1]
data_stream_name_r = ["t", "ph", "i0", "i1", "i2", "i3"]
data_stream_value_r = [0, 0, 0, 0, 0, 0]

lt1 = 0  # second count
start = 0
c = MQTTClient(CLIENT_ID, SERVER, SERVER_PORT, username, password)

rtc = RTC()

wlan = network.WLAN(network.STA_IF)

wifi_error = 1
ntp_error = 1

i2c0 = I2C(0, scl=Pin(18), sda=Pin(19), freq=400000)
oled_width = 128
oled_height = 64
oled = SSD1306_I2C(oled_width, oled_height, i2c0)  # Initializing the OLED display

i2c1 = I2C(1, scl=Pin(25), sda=Pin(26), freq=400000)
adc = ADS1115(i2c1, 72, 0)
adc_raw = [0, 0, 0, 0]
adc_v = [0.0, 0.0, 0.0, 0.0]

pwm0 = PWM(Pin(5))


# pin2 can not be pulled down to 0V
GPO = [23, 22, 21, 4, 15, 32, 33, 27, 2]
PinO = [23, 22, 21, 4, 15, 32, 33, 27, 2]

GPI = [ 13, 14, 34, 35]
PinI = [ 13, 14, 34, 35]

TMP = 24.0
PH=7.0
rr=0.05
power = 0
# power ctrl
deltT=0.5
setTMP=24.0
# bump ctrl
b_start=0
b_start_t=0
W_level=[0,0,0,0]
#light
autoLight=1
light=0

def wifi_connect():
    global wifi_error
    wlan.active(True)
    reco = 0
    if not wlan.isconnected():
        print('connecting to network ')
        wlan.connect(wlan_ssid, wlan_passwd)
    while not wlan.isconnected():
        reco = reco + 1
        time.sleep_ms(500)
        print(".", end="")
        if reco == 20:
            print('')
            print('WIFI error')
            wifi_error = 1
            break
    if wlan.isconnected():
        print('')
        print('network config:', wlan.ifconfig())
        wifi_error = 0


def check_wlan():
    global wifi_error
    if not wlan.isconnected():
        print('WIFI error')
        wifi_error = 1
        # wlan.connect(wlan_ssid, wlan_passwd)
    else:
        wifi_error = 0


def sync_ntp():
    global ntp_error
    ntptime.NTP_DELTA = 3155644800
    ntptime.host = 'ntp1.aliyun.com'
    if wlan.isconnected():
        try:
            ntptime.settime()
            ntp_error = 0
        except:
            #ntp_error = 1
            print("ntp error")


def pack_msg(message):
    msglen = len(message)
    tmp = [0, 0, 0]
    tmp[0] = '\x03'
    tmp[1] = msglen >> 8
    tmp[2] = msglen & 0XFF
    message = "%c%c%c%s" % (tmp[0], tmp[1], tmp[2], message)
    return message


def sub_cb(topic, msg):  # rev
    global state
    global b_start
    global b_start_t
    global pwm0
    global autoLight
    # msg=b"porwer:95"
    print(msg)
    msg1 = bytes.decode(msg)
    [tmp1, tmp2] = msg1.split(':')
    tmp3 = int(tmp2)
    trans = 0
    for i in range(len(data_stream_name_rw)):
        if tmp1 == data_stream_name_rw[i]:
            data_stream_value_rw[i] = tmp3
            trans = trans + 1
            if i==0 :
                if tmp3==1:
                    b_start=1
                    b_start_t=0
                elif tmp3==0:
                    b_start=0
                    b_start_t=0
            if i==9 :
                if tmp3<=1:
                    autoLight=1
                else :
                    autoLight=0
                    MyLight(tmp3)
    if trans > 0:
        msg = "{\"%s\":%s}" % (tmp1, tmp2)
        print(msg)
        msg = pack_msg(msg)
        JDctrl()
        # print(data_stream_value_rw)
        try:
            c.publish(TOPIC, msg)
        except:
            print("pub_error")
            c.reconnect()


def apptimerevent(mytimer):  # 0.1s
    global lt1
    global TMP
    global PH
    global power
    global W_level
    global b_start_t
    lt1 = lt1 + 1
    if lt1 % 10 == 0:
        per_1sec()
    if lt1 % 50 == 0:
        per_5sec()
    if lt1 % 600 == 0:
        per_1min()
    for i in range(0, 4):
        adc_raw[i] = adc.read(4, i)
        adc_v[i] = adc.raw_to_v(adc_raw[i])
    TMP = TMP*(1-rr)+v_to_TMP(adc_v[0], adc_v[1])*rr
    PH = PH *(1-rr)+v_to_PH(adc_v[2])*rr
    Powerctrl()
    if lt1 % 100<power:
        GPO[8].value(0)
    else :
        GPO[8].value(1)
    for i in range(0, 4):
        if GPI[i].value()==0 :
            W_level[i]=1
        else :
            W_level[i] = 0
        data_stream_value_r[i + 2] = W_level[i]
    if W_level[0]==1 or W_level[0]==1 :
        b_start_t=0
    ProtSkim()

def per_1min():  # 60s
    check_wlan()
    sync_ntp()

def per_5sec():  # 5s
    aa=0


def per_1sec():  # 1s
    global TMP
    global PH
    global b_start_t
    global light
    data_stream_value_r[0] = TMP
    data_stream_value_r[1] = PH
    msg = "{\"%s\":%.2f,\"%s\":%.2f,\"%s\":%d,\"%s\":%d,\"%s\":%d,\"%s\":%d}" % (
        data_stream_name_r[0], data_stream_value_r[0], data_stream_name_r[1], data_stream_value_r[1], data_stream_name_r[2], data_stream_value_r[2], data_stream_name_r[3], data_stream_value_r[3], data_stream_name_r[4], data_stream_value_r[4], data_stream_name_r[5], data_stream_value_r[5])
    print(msg)
    msg = pack_msg(msg)
    try:
        c.publish(TOPIC, msg)
    except:
        print("pub_error")
        c.reconnect()
    localtime = time.localtime()
    print(localtime)
    oled.fill(0)
    line1 = "%d,%02d,%02d" % (localtime[0], localtime[1], localtime[2])
    line2 = "%02d:%02d:%02d PH=%.2f" % (localtime[3], localtime[4], localtime[5],PH)
    line3 = "TMP=%05.2f P=%03d" % (TMP,power)
    line4 = "%d %d %d %d %d %d %d %d" % (data_stream_value_rw[0],data_stream_value_rw[1],data_stream_value_rw[2],data_stream_value_rw[3],data_stream_value_rw[4],data_stream_value_rw[5],data_stream_value_rw[6],data_stream_value_rw[7])
    line5 = "%d %d %d %d" % (data_stream_value_r[2],data_stream_value_r[3],data_stream_value_r[4],data_stream_value_r[5])
    oled.text(line1, 0, 0)
    oled.text(line2, 0, 10)#max 16 char
    oled.text(line3, 0, 20)
    oled.text(line4, 0, 30)
    oled.text(line5, 0, 40)
    oled.show()


    msg = "%.3f\t%.3f\t%.3f\t%.3f" % (adc_v[0], adc_v[1], adc_v[2], adc_v[3])

    #    msg="%d\t%d\t%d\t%d"%(adc_raw[0],adc_raw[1],adc_raw[2],adc_raw[3])
    print(msg)
    msg = "b_start:%d  ProtSkim Delay : %03d" % (b_start,b_start_t)
    print(msg)
    if ntp_error == 0 and autoLight==1:
        if localtime[3]>=12 and localtime[3]<23 :
            if light<100 :
                light=light+1
        else :
            if light>0 :
                light=light-1
        MyLight(light)



def JDctrl():
    #  print(data_stream_value_rw)
    #for i in range(len(PinO)):
    for i in range(0,8):
        print(data_stream_value_rw[i])
        if i!=1 :
            if data_stream_value_rw[i] == 1:
                GPO[i].value(0)
            else:
                GPO[i].value(1)
def ProtSkim():
    global b_start
    global b_start_t
    global W_level
    if b_start==1 and b_start_t<450:#30~45s
        b_start_t=b_start_t+1

    elif b_start==0 :
        b_start_t=0
    if (b_start_t>=450 and data_stream_value_rw[1]==1) and (W_level[0]==0 and W_level[1]==0):
        GPO[1].value(0)
    else:
        GPO[1].value(1)

def MyPinSet():
    global pwm0
    for i in range(len(PinO)):
        GPO[i] = Pin(PinO[i], Pin.OUT)
        GPO[i].value(1)
    for i in range(len(PinI)):
        GPI[i] = Pin(PinI[i], Pin.IN, Pin.PULL_UP)
    pwm0.freq(5000)
    pwm0.duty(0)

def MyLight(ll):
    global pwm0
    pwm0.duty(int(0.0986 * ll * ll + 37))

def v_to_TMP(vo, vi):
    R1 = 9600.0
    # 5.025 2.454
    R = vo * R1 / (vi - vo)
    R = R / 1000
    T = -0.0020 * R * R * R + 0.1678 * R * R - 5.4817 * R + 65.3095
    return T


def v_to_PH(vi):
    v700 = 3.00
    v401 = 3.534
    dph = 2.99/(v700 - v401)
    return dph * (vi - v700) + 7.0

def Powerctrl():
    global TMP
    global setTMP
    global deltT
    global power
    if data_stream_value_rw[8] == 1:
        if TMP<(setTMP-deltT):
            power=100
        elif TMP<setTMP:
            err=(setTMP - TMP)*200
            power=int(err)
        else :
            power=0
    else:
        power=0





def main(server=SERVER):
    machine.freq(240000000)
    MyPinSet()
    wifi_connect()
    oled.fill(0)
    oled.text('Welcome to Lab!', 0, 0)
    oled.text('Welcome to Lab!', 0, 10)
    oled.text('Welcome to Lab!', 0, 20)
    oled.show()
    check_wlan()
    global c
    c.DEBUG = True
    c.set_callback(sub_cb)
    if not c.connect(clean_session=False):
        print("New session being set up")
        print("Connected to %s, uploading DHT11 data to server" % server)
        c.subscribe(TOPIC1)

    print("Connected to %s, subscribed to %s topic" % (server, TOPIC1))
    mytimer = Timer(3)
    mytimer.init(mode=Timer.PERIODIC, period=100, callback=apptimerevent)
    start = time.ticks_ms()
    try:
        while 1:
            try:
                c.wait_msg()
            except:
                print("wait_error")
                c.reconnect()

    finally:
        c.disconnect()




